package com.mcptt.http.auth.process.passwd;

import com.cloudptt.api.product.log.Log;
import com.cloudptt.api.product.res.Resource;
import com.mcptt.http.auth.process.HttpAuthFailedException;
import com.mcptt.http.auth.process.HttpProcessor;
import com.mcptt.http.auth.process.HttpSubProcessor;
import com.mcptt.http.auth.process.passwd.result.FirstGetResult;
import com.mcptt.http.auth.process.passwd.result.FirstPostResult;
import com.mcptt.http.auth.process.result.FinalResult;
import com.mcptt.http.tool.EncryptionTool;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import okhttp3.Response;

public class HttpPasswdSubProcessor extends HttpSubProcessor
{

	public HttpPasswdSubProcessor(URI authUri, URI loginUri, URI tokenUri)
	{
		super(authUri,loginUri,tokenUri);
	}

	public void runAuthorization(String clientId, String redirectUri,String mcId,String pwd) throws Exception
	{
		String state = getState();
		Log.debug(this.getClass(), "doAuthorization clientId = " + clientId + " redirectUri = " + redirectUri + " mcId = " + mcId + " state = " + state);
		FirstGetResult firstResult = doFirstGet(clientId, redirectUri,state);
		Log.debug(this.getClass(), "firstResult = " + firstResult + " firstResult.isSuc() = " + firstResult.isSuc());
		if(!firstResult.isSuc())
		{
			String errStr = firstResult.getErrStr();
			Exception e =  new HttpAuthFailedException("doFirstGet",errStr);
			sendAuthResultMsg(AUTH_FAILED,e);
			return;
		}
		if(!firstResult.checkReturnParamOk())
		{
			Exception e = new HttpAuthFailedException("doFirstGet","Return Param less");
			sendAuthResultMsg(AUTH_FAILED,e);
			return;
		}

		String cookie = firstResult.getCookie();
		FirstPostResult firstPostResult = doFirstPost(cookie,mcId,pwd);
		Log.debug(this.getClass(), "firstPostResult = " + firstPostResult + " firstPostResult.isSuc() = " + firstPostResult.isSuc());
		if(firstPostResult.getResult() == 403)
		{
//			String errStr = Resource.getString("e_login_err_license");
			Exception e =  new HttpAuthFailedException("doFirstPost",HttpAuthFailedException.ErrCode_License,LOGIN_ERR_LICENSE);
			sendAuthResultMsg(AUTH_FAILED,e);
			return;
		}
		if(!firstPostResult.isSuc())
		{
			String errStr = firstPostResult.getErrStr();
			Exception e =  new HttpAuthFailedException("doFirstPost",HttpAuthFailedException.ErrCode_Passward,errStr);
			sendAuthResultMsg(AUTH_FAILED,e);
			return;
		}
		Log.debug(this.getClass(),  "firstPostResult.checkReturnParamOk() = " + firstPostResult.checkReturnParamOk());
		if(!firstPostResult.checkReturnParamOk())
		{
			Exception e =  new HttpAuthFailedException("doFirstPost","Return Param less");
			sendAuthResultMsg(AUTH_FAILED,e);
			return;
		}

		String codeStr = firstPostResult.getCode();
//		String newCookie = firstResult.getCookie();
		Log.debug(this.getClass(), "codeStr = " + codeStr );
		FinalResult finalResult = doFinalPost(codeStr, clientId, redirectUri,null);
		Log.debug(this.getClass(), "finalResult = " + finalResult + " finalResult.isSuc() = " + finalResult.isSuc());
		if(!finalResult.isSuc())
		{
			String errStr = finalResult.getErrStr();
			Exception e =  new HttpAuthFailedException("doFinalPost",errStr);
			sendAuthResultMsg(AUTH_FAILED,e);
			return;
		}
		Log.debug(this.getClass(),  "finalResult.checkReturnParamOk() = " + finalResult.checkReturnParamOk());
		if(!finalResult.checkReturnParamOk())
		{
			Exception e =  new HttpAuthFailedException("doFinalPost","Return Param less");
			sendAuthResultMsg(AUTH_FAILED,e);
			return;
		}
		sendAuthResultMsg(AUTH_SUC,finalResult);
		//	return finalResult;
	}



	public FirstGetResult doFirstGet(String clientId, String redirectUri, String state) throws Exception
	{
		Log.debug(getClass(), "doFirstGet clientId = " + clientId + " redirectUri = " + redirectUri + " state = " + state);
		FirstGetResult result = null;
		String str = getVerifierCode();
		Log.debug(getClass(), "doFirstGet str = " + str);
		String newStr = EncryptionTool.getEncryptionStr(str);
		Log.debug(getClass(), "doFirstGet 1 str = " + str + " newStr = " + newStr);
//		newStr = EncryptionTool.encodeBase64(newStr);
//		Log.debug(getClass(), "doFirstGet 2 str = " + str + " newStr = " + newStr);
		if (newStr == null)
		{
			result = new FirstGetResult(
					FirstGetResult.FirstGetResult_EncryptionEx, "");
			return result;
		}

		Map<String,String> paramsMap = new HashMap<String,String>();
		paramsMap.put("response_type", "code");
		paramsMap.put("client_id", clientId);
		paramsMap.put("redirect_uri", redirectUri);
		paramsMap.put("scope", getSocpStr());
		paramsMap.put("state", state);
		paramsMap.put("acr_values", getAcrStr());
//		paramsMap.put("acr_values", "3gpp:acr:digest");
		paramsMap.put("code_challenge", newStr);
		paramsMap.put("code_challenge_method", getChallengeMethod());

		Response httpResponse = this.operator.httpGetRequest(authUri.toString(), paramsMap);
		int code = httpResponse.code();
		Log.debug(getClass(), "doFirstGet code = " + code);
		if (code == 200)
		{
			String desc = httpResponse.body().toString();
			result = new FirstGetResult(code, desc);

//			String location = httpResponse.header("Location");
//			result.setLocation(location);
			if(httpResponse.header("Set-Cookie") != null)
			{
				String cookie = httpResponse.header("Set-Cookie");
				Log.debug(getClass(), "doFirstGet cookie = " + cookie);
				result.setCookie(cookie);
			}
		}
		else
		{
			String desc = "Error Response: "
					+ httpResponse.code();
			result = new FirstGetResult(code, desc);
		}

		return result;
	}

	public FirstPostResult doFirstPost(String cookie,String mcId,String pwd) throws Exception
	{
		Log.debug(getClass(), "doFirstPost mcId = " + mcId + " pwd = *** cookie = " + cookie);
		FirstPostResult result = null;
		Map<String, String> params = new HashMap<String, String>();
		params.put("username", mcId);
		params.put("password", pwd);
		Response httpResponse = this.operator.httpPostRequest(loginUri.toString(), cookie,params);
		if(httpResponse == null)
		{
			String desc = "Error Response: "
					+ httpResponse.code();
			result = new FirstPostResult(404, desc);
			return result;
		}
		int code = httpResponse.code();
		Log.debug(getClass(), "doFirstPost code = " + code);
		if (code == 302)
		{
			String desc = httpResponse.body().toString();
			result = new FirstPostResult(code, desc);

			String location = httpResponse.header("Location");
			Log.debug(getClass(), "doFirstPost location = " + location);
			result.setLocation(location);
			if(httpResponse.header("Set-Cookie") != null)
			{
				String newCookie = httpResponse.header("Set-Cookie");
				Log.debug(getClass(), "doFirstGet newCookie = " + newCookie);
				result.setCookie(newCookie);
			}
		}
		else
		{
			String desc = "Error Response: "
					+ httpResponse.code();
			result = new FirstPostResult(code, desc);
		}

		return result;
	}

	public FinalResult doFinalPost(String codeStr,String clientId,String redirectUri,String cookie) throws Exception
	{
		Log.debug(getClass(), "doFinalPost codeStr = " + codeStr + " clientId = " + clientId + " redirectUri = " + redirectUri + " cookie = " + cookie);
		FinalResult result = null;
		Map<String, String> params = new HashMap<String, String>();
		params.put("grant_type", "authorization_code");
		params.put("code", codeStr);
		params.put("client_id", clientId);
		params.put("redirect_uri", redirectUri);
		params.put("code_verifier", getVerifierCode());
//		this.operator.httpPostRequest(tokenUri.toString(), params);
		Response httpResponse = this.operator.httpPostRequest(tokenUri.toString(),cookie, params);
		int code = httpResponse.code();
		Log.debug(getClass(), "doFinalPost code = " + code);
		if (code == 200
				|| code == 400)
		{
			/* ���X�^���r�� */
			String desc = httpResponse.body().string();
			Log.debug(getClass(), "doFinalPost desc = " + desc);
			result = new FinalResult(code, desc);
		}
		else
		{
			String desc = "Error Response: "
					+ httpResponse.code();
			result = new FinalResult(code, desc);
		}
		return result;
	}

	public String getAcrStr()
	{
		return "3gpp:acr:password";
	}
	public String getChallengeMethod()
	{
		return "S256";
	}
	protected void initSocpStr()
	{
		StringBuffer strBuf = new StringBuffer(Socp_Openid);
		strBuf.append("%20").append(Socp_Ptt_Svr);
//		strBuf.append("%20").append(Socp_Ptt_Key_Svr);
		strBuf.append("%20").append(Socp_Ptt_Config_Svr);
		strBuf.append("%20").append(Socp_Ptt_Group_Svr);

		strBuf.append("%20").append(Socp_Video_Svr);
//		strBuf.append("%20").append(Socp_Video_Key_Svr);
		strBuf.append("%20").append(Socp_Video_Config_Svr);
		strBuf.append("%20").append(Socp_Video_Group_Svr);

		strBuf.append("%20").append(Socp_Data_Svr);
//		strBuf.append("%20").append(Socp_Data_Key_Svr);
		strBuf.append("%20").append(Socp_Data_Config_Svr);
		strBuf.append("%20").append(Socp_Data_Group_Svr);
		strBuf.append("%20").append(Socp_Location_Svr);

		this.socpStr = strBuf.toString();
	}
	public String getState()
	{
		long value = (int) ((Math.random() * 9 + 1) * 10000000);
		return "" + value;
//		return "8a9e4688-0273-44ac-8923-ef2b66b2b1b5";
	}
}
